package com.imooc.game.pintu.view;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.imooc.game.pintu.R;
import com.imooc.game.utils.ImagePiece;
import com.imooc.game.utils.ImageSplitterUtil;

public class GamePintuLayout extends RelativeLayout implements OnClickListener
{

	private int mColumn = 3;
	/**
	 * 容器的内边距
	 */
	private int mPadding;
	/**
	 * 每张小图之间的距离（横、纵） dp
	 */
	private int mMargin = 3;

	private ImageView[] mGamePintuItems;

	private int mItemWidth;

	/**
	 * 游戏的图片
	 */
	private Bitmap mBitmap;

	private List<ImagePiece> mItemBitmaps;

	/**
	 * 想要唯一操作时使用
	 */
	private boolean once;

	/**
	 * 游戏面板的宽度
	 */
	private int mWidth;

	private boolean isGameSuccess;
	private boolean isGameOver;

	
	/**
	 * 通过回调接口 告诉主界面 执行下一关!
	 * @author zxy
	 *
	 */
	public interface GamePintuListener
	{
		void nextLevel(int nextLevel);

		void timechanged(int currentTime);

		void gameover();
	}

	public GamePintuListener mListener;

	/**
	 * 设置接口回调
	 * 
	 * @param mListener
	 */
	public void setOnGamePintuListener(GamePintuListener mListener)
	{
		this.mListener = mListener;
	}

	private int mLevel = 1;
	
	//下一关,更新时间!
	private static final int TIME_CHANGED = 0x110;
	private static final int NEXT_LEVEL = 0x111;

	
	//?句柄? !向日志文件发送信息!
	private Handler mHandler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
			switch (msg.what)
			{
			case TIME_CHANGED:
				
				//※如果游戏过关、游戏结束、游戏暂停,时间不动!
				if (isGameSuccess || isGameOver || isPause)
					return;
				if (mListener != null)
				{
					//通知主界面去修改时间
					mListener.timechanged(mTime);
				}
				if (mTime == 0)
				{
					isGameOver = true;
					mListener.gameover();
					return;
				}
				
				//倒计时
				mTime--;
				
				/**
				 * ※发送就监听(回调)  ∴每隔一秒减少1s时间 做到无限循环!!!
				 * 不用线程,以免产生并发问题
				 */
				mHandler.sendEmptyMessageDelayed(TIME_CHANGED, 1000);

				break;
			case NEXT_LEVEL:
				mLevel = mLevel + 1;
				if (mListener != null)
				{
					mListener.nextLevel(mLevel);
				} else
				{
					nextLevel();
				}
				break;

			}
		};
	};

	private boolean isTimeEnabled = false;
	//计时用 时间
	private int mTime;

	/**
	 * 设置是否开启时间
	 * 
	 * @param isTimeEnabled
	 */
	public void setTimeEnabled(boolean isTimeEnabled)
	{
		this.isTimeEnabled = isTimeEnabled;
	}

	public GamePintuLayout(Context context)
	{
		this(context, null);
	}

	public GamePintuLayout(Context context, AttributeSet attrs)
	{
		this(context, attrs, 0);
	}

	public GamePintuLayout(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		init();
	}

	private void init()
	{
		/**
		 * dp转为px保证不同设备图片大小几乎一致
		 */
		mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
				3, getResources().getDisplayMetrics());
		/**
		 * 无论用户设置各边距大小多不同，取最小使其相同
		 */
		mPadding = min(getPaddingLeft(), getPaddingRight(), getPaddingTop(),
				getPaddingBottom());
	}

	
	/**
	 * Measure 测量
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 取宽和高中的小值，以防有的设备解析成长方形，强制改为正方形
		mWidth = Math.min(getMeasuredHeight(), getMeasuredWidth());

		if (!once)
		{
			// 进行切图，以及排序
			initBitmap();
			// 设置ImageView(Item)的宽高等属性
			initItem();
			// 判断是否开启时间
			checkTimeEnable();

			once = true;
		}
		
		/**
		 * 强制改为正方形
		 */
		setMeasuredDimension(mWidth, mWidth);

	}

	
	/**
	 * 判断是否开启时间
	 */
	private void checkTimeEnable()
	{
		if (isTimeEnabled)
		{
			// 根据当前等级设置时间
			countTimeBaseLevel();
			mHandler.sendEmptyMessage(TIME_CHANGED);
		}

	}

	private void countTimeBaseLevel()
	{
		/**
		 * 因为图片难度是指数增长,所以时间指数增长是合理的!
		 * 2^第几关  * 60s
		 */
		mTime = (int) Math.pow(2, mLevel) * 60;
	}

	/**
	 * 进行切图，以及排序
	 */
	private void initBitmap()
	{
		if (mBitmap == null)
		{
			mBitmap = BitmapFactory.decodeResource(getResources(),
					R.drawable.image);
		}
		/**
		 * 切成的每一块
		 */
		mItemBitmaps = ImageSplitterUtil.splitImage(mBitmap, mColumn);

		// 使用sort<排序函数>完成我们的乱序
		Collections.sort(mItemBitmaps, new Comparator<ImagePiece>()
		{
			@Override
			public int compare(ImagePiece a, ImagePiece b)
			{
				/**
				 * 使两个数比较的大小成为1/2概率,以实现乱序
				 */
				return Math.random() > 0.5 ? 1 : -1;
			}
		});

	}

	/**
	 * 设置ImageView(Item)的宽高等属性
	 */
	private void initItem()
	{
		/**
		 * mItemWidth 每一个小切图的宽度
		 * mPadding外边距 (only左右)
		 * mMargin 切图间隙
		 */
		mItemWidth = (mWidth - mPadding * 2 - mMargin * (mColumn - 1))
				/ mColumn;
		mGamePintuItems = new ImageView[mColumn * mColumn];
		// 生成我们的Item，设置Rule
		for (int i = 0; i < mGamePintuItems.length; i++)
		{
			ImageView item = new ImageView(getContext());
			
			/**
			 * 点击事件,已继承此类
			 */
			item.setOnClickListener(this);
			item.setImageBitmap(mItemBitmaps.get(i).getBitmap());

			mGamePintuItems[i] = item;
			item.setId(i + 1);

			/**
			 * 虽是乱序,但每一个item中存的index是这个位置真正的顺序,用以判断拼图是否完成
			 * 
			 * ※※※整个程序的关键: 在每一个Item<List>中 存了一个id(i)<当前Item位置> 
			 * ※※※还存了一个index<当前Item原来的真正的位置>
			 */
			// 在Item的tag中存储了index
			item.setTag(i + "_" + mItemBitmaps.get(i).getIndex());

			RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
					mItemWidth, mItemWidth);

			/**
			 * Item.i
			 * 0	1	2	3
			 * 4	5	6	7
			 * 8	9	10	11
			 */
			// 设置Item间横向间隙，通过rightMargin
			
			
			/**
			 * 设置右边距
			 */
			// 不是最后一列
			if ((i + 1) % mColumn != 0)
			{
				lp.rightMargin = mMargin;
			}
			
			
			/**
			 * 设置左边距(往右推)RIGHT_OF
			 */
			// 不是第一列
			if (i % mColumn != 0)
			{
				lp.addRule(RelativeLayout.RIGHT_OF,
						mGamePintuItems[i - 1].getId());
			}
			
			
			/**
			 * 设置上边距 (往下推)BELOW
			 */
			// 如果不是第一行 , 设置topMargin和rule
			if ((i + 1) > mColumn)
			{
				lp.topMargin = mMargin;
				
				/**
				 * 谁在谁的下面
				 */
				lp.addRule(RelativeLayout.BELOW,
						mGamePintuItems[i - mColumn].getId());
			}
			addView(item, lp);
		}

	}

	/**
	 * ※?当前关?※重开
	 */
	public void restart()
	{
		isGameOver = false;
		mColumn--;
		nextLevel();
	}
	
	private boolean isPause ; 
	
	/**
	 * 暂停!! 恢复!!
	 */
	public void pause()
	{
		isPause = true ; 
		//去掉消息(Messages)
		mHandler.removeMessages(TIME_CHANGED);
	}
	
	public void resume()
	{
		if(isPause)
		{
			isPause = false ;
			//发送消息
			mHandler.sendEmptyMessage(TIME_CHANGED);
		}
	}

	//下一关
	public void nextLevel()
	{
		this.removeAllViews();
		mAnimLayout = null;
		mColumn++;
		//新的开始
		isGameSuccess = false;
		checkTimeEnable();
		initBitmap();
		initItem();
	}

	/**
	 * 获取多个参数的最小值
	 */
	/**
	 * 
	 * @param params 任意多 个参数
	 * @return
	 */
	private int min(int... params)
	{
		int min = params[0];
		
		/**
		 * 增强的for循环
		 */
		for (int param : params)
		{
			if (param < min)
				min = param;
		}
		return min;
	}

	private ImageView mFirst;
	private ImageView mSecond;
	
	
	/**
	 * 点击事件处理
	 */
	@Override
	public void onClick(View v)
	{
		//防止(动画进行中用户的任何操作都清空)错误操作<疯狂的点>
		if (isAniming)
			return;

		
		/**
		 * 特殊操作,重复点击 则去掉高亮
		 */
		// 两次点击同一个Item
		if (mFirst == v)
		{
			mFirst.setColorFilter(null);
			mFirst = null;
			return;
		}
		if (mFirst == null)
		{
			mFirst = (ImageView) v;
			
			/**
			 * 被点击的图片呈选中状态(颜色变化 透明红)<#透明度RGB>
			 */
			mFirst.setColorFilter(Color.parseColor("#55FF0000"));
		} else
		{
			mSecond = (ImageView) v;
			// 交换我们的Item
			exchangeView();
		}

	}

	/**
	 * 动画层
	 */
	private RelativeLayout mAnimLayout;
	private boolean isAniming;

	/**
	 * 交换我们的Item
	 */
	private void exchangeView()
	{
		//去掉高亮
		mFirst.setColorFilter(null);
		
		// 构造我们的动画层
		setUpAnimLayout();

		
		/**
		 * 复制first&second
		 */
		ImageView first = new ImageView(getContext());
		
		/**
		 * getTag获取item(即切的某一小块)
		 */
		final Bitmap firstBitmap = mItemBitmaps.get(
				getImageIdByTag((String) mFirst.getTag())).getBitmap();
		
		/**
		 * ?交换无需设置中间变量  ∵是通过setImageBitmap获 取变量?
		 */
		first.setImageBitmap(firstBitmap);
		
		//动画层
		LayoutParams lp = new LayoutParams(mItemWidth, mItemWidth);
		
		
		/**
		 * 动画层也要计算类(外)边距
		 * Item相对于动画层类边距为0,但相对于最外层类边距为mPadding
		 */
		lp.leftMargin = mFirst.getLeft() - mPadding;
		lp.topMargin = mFirst.getTop() - mPadding;
		first.setLayoutParams(lp);
		mAnimLayout.addView(first);

		ImageView second = new ImageView(getContext());
		final Bitmap secondBitmap = mItemBitmaps.get(
				getImageIdByTag((String) mSecond.getTag())).getBitmap();
		/**
		 * 交换完成
		 * 层的动画开始...
		 */
		second.setImageBitmap(secondBitmap);
		
		LayoutParams lp2 = new LayoutParams(mItemWidth, mItemWidth);
		lp2.leftMargin = mSecond.getLeft() - mPadding;
		lp2.topMargin = mSecond.getTop() - mPadding;
		second.setLayoutParams(lp2);
		mAnimLayout.addView(second);

		// 设置动画
		TranslateAnimation anim = new TranslateAnimation(0, mSecond.getLeft()
				- mFirst.getLeft(), 0, mSecond.getTop() - mFirst.getTop());
		anim.setDuration(300);
		anim.setFillAfter(true);
		first.startAnimation(anim);

		TranslateAnimation animSecond = new TranslateAnimation(0,
				-mSecond.getLeft() + mFirst.getLeft(), 0, -mSecond.getTop()
						+ mFirst.getTop());
		animSecond.setDuration(300);
		animSecond.setFillAfter(true);
		second.startAnimation(animSecond);

		// 监听动画
		anim.setAnimationListener(new AnimationListener()
		{
			
			//动画Start
			@Override
			public void onAnimationStart(Animation animation)
			{
				//原本(真)的View 隐藏
				mFirst.setVisibility(View.INVISIBLE);
				mSecond.setVisibility(View.INVISIBLE);

				isAniming = true;
			}

			@Override
			public void onAnimationRepeat(Animation animation)
			{
				// TODO Auto-generated method stub

			}

			//动画End
			@Override
			public void onAnimationEnd(Animation animation)
			{

				String firstTag = (String) mFirst.getTag();
				String secondTag = (String) mSecond.getTag();

				//在层下偷偷交换图片
				mFirst.setImageBitmap(secondBitmap);
				mSecond.setImageBitmap(firstBitmap);

				
				/**
				 * Tag-标签
				 */
				mFirst.setTag(secondTag);
				mSecond.setTag(firstTag);

				//再偷偷的把层下 交换后的两个隐藏图片显示出来
				mFirst.setVisibility(View.VISIBLE);
				mSecond.setVisibility(View.VISIBLE);

				/**
				 * 置于初始状态
				 */
				mFirst = mSecond = null;
				
				//去掉动画层上的两个图片
				mAnimLayout.removeAllViews();
				
				// 判断用户游戏是否成功
				checkSuccess();
				isAniming = false;
			}
		});

	}

	/**
	 * 判断用户游戏是否成功
	 */
	private void checkSuccess()
	{
		boolean isSuccess = true;

		for (int i = 0; i < mGamePintuItems.length; i++)
		{
			ImageView imageView = mGamePintuItems[i];
			if (getImageIndexByTag((String) imageView.getTag()) != i)
			{
				isSuccess = false;
			}
		}

		if (isSuccess)
		{
			isGameSuccess = true;
			
			//※解决倒计时速度叠加
			mHandler.removeMessages(TIME_CHANGED);

			Toast.makeText(getContext(), "Success ， level up !!!",
					Toast.LENGTH_LONG).show();
			
			//Handler向日志文件发送一个(NEXT_LEVEL)消息
			mHandler.sendEmptyMessage(NEXT_LEVEL);
		}

	}

	/**
	 * 根据tag获取Id
	 * 
	 * @param tag
	 * @return
	 */
	public int getImageIdByTag(String tag)
	{
		String[] split = tag.split("_");
		return Integer.parseInt(split[0]);
	}

	public int getImageIndexByTag(String tag)
	{
		String[] split = tag.split("_");
		return Integer.parseInt(split[1]);
	}

	/**
	 * 构造我们的动画层
	 */
	private void setUpAnimLayout()
	{
		if (mAnimLayout == null)
		{
			mAnimLayout = new RelativeLayout(getContext());
			//将这个层加到面板之中
			addView(mAnimLayout);
		}
	}

}
